\subsection{Ejercicio 6}

El ejercicio 6 nos pide crear una función \code{void cargar\_tarea(unsigned int desde, unsigned int indice)}
Esta función debe:
\begin{itemize}
\item Obtener las páginas libres de usuario para el código y para la pila.
\item Obtener una página libre para la pila de nivel 0.
\item Crear un directorio de páginas de usuario.
\item Mapear las direcciones correctamente.
\item Copiar el código a la dirección física correspondiente.
\item Inicializar el TSS que correponda el índice.
\item Inicializar la entrada de la GDT que corresponda al índice.
\end{itemize}
Para poder cargar una tarea utilizamos los archivos dados por la cátedra.El archivo \code{TSS.h} define la 
estructura del espacio donde guardar el contexto. El archivo \code{TSS.c} declara un array de tss llamado tsss. \\
	Esta es la estructura de la \code{TSS}:

\begin{center}
\includegraphics[scale=0.4]{tss.png}
\end{center}

	Estas \code{TSS} ubicadas en memoria, necesitan de descriptores particulares (descriptores de tareas) en nuestra \code{GDT}, para así poder 
ubicarlos. 

Para este item se implementó en el archivo \code{loader.c} la función \code{cargar\_tarea}. La función se encarga de inicializar la tss, y realizar los mapeos necesarios para cargar la tarea. \\
\indent Comienza obteniendo una página libre de kernel (para la pila que será usada por el kernel) y tres páginas de usuario (dos para el código de la tarea y una para la pila de usuario) y luego, realizando los mapeos necesarios \\

	\indent \code{mapear\_pagina(0x00000000, (unsigned int) dir\_usuario, (unsigned int) cod\_usuario3\_1, 7)}\\
	\indent \code{mapear\_pagina(TAMANO\_PAGINA, (unsigned int) dir\_usuario, (unsigned int) cod\_usuario3\_2, 7)}\\
 	\indent \code{mapear\_pagina((unsigned int) pila3, (unsigned int) dir\_usuario, (unsigned int) pila3, 7)} \\
 	\indent \code{mapear\_pagina((unsigned int) pila0, (unsigned int) dir\_usuario, (unsigned int) pila0, 3)} \\
\\Ésto quiere decir que:\\
Se mapean 8K para código de la tarea desde la dirección virtual 0x0000000, se mapean con identity mapping 4K para la pila de anillo 3 y se mapean con identity mapping otros 4K para la pila de anillo 0\\
Luego copia el codigo de la tarea a las páginas de usuario reservadas para el código.\\
A continuación inicializa la TSS de la tarea:\\
\indent Pilas: \\
En tsss[indice].esp0 pone la dir de pila0 + 4K que es el tamaño de la pila.\\
Inicializarla como dir de pila0 sería incorrecto, porque se expande hacia abajo, y en ese caso entraría en otra página. 
En el resto de los campos se setea todo en 0 a excepcion de tsss[indice].esp0 que pone 0x10. Es la pila del kernel, por lo tanto se necesita que utilice el segmento de datos en modo supervisor\\

\indent MMU: \\
En la tsss[indice].cr3 se le asigna la dirección física del directorio inicializado para la tarea.\\
\indent Registros: \\
Los registros se setean todos en 0, ya que estamos inicializando la tss de una tarea que aun no se ejecutó.\\
El registro EIP, particularmente, se setea en 0 porque corresponde a la dirección virtual de inicio de las instrucciones de dicha tarea.
En el registro eflags asignamos 0x202 ya que tenemos que habilitar las interrupciones.\\
Los registros de segmento los seteamos en 0x28, y el cs en 0x20. Porque corresponden a los segmentos de datos y de código de usuario, respectivamente, y serán accedidas desde anillo 3 (ésto es, con CPL = 3)\\
Por último seteamos el iomap en 0xFFFF. Nos ayuda cuando debuggeamos a saber donde termina la TSS y empieza otra.\\

\indent Descriptores de TSS: \\
La función finaliza inicializando el descriptor de la  \code{TSS} en la \code{GDT}:
A continuación, un gráfico con las componentes del descriptor. 

\begin{center}
\includegraphics[scale=0.4]{tss_descriptor.png}
\end{center}

A la base del descriptor se le asigna la dirección de memoria de \code{tss[indice]}. Se activa el bit de presente, al campo \code{TYPE} se le asigna 0x9, seteando en 0 el bit de \code{Busy}. Los bits de S, DPL y AVL se setean en 0, lo que significa que es un descriptor de Sistema de privilegio 0.\\ 

En el siguiente item nos piden modificar la \code{IDT} para que las interrupciones 88 y 89 puedan ser llamadas desde el desde privilegio 3.\\

Para esto se tuvo que cambiar en el archivo idt.c en la función \code{inicializar\_IDT} los atributos, que en lugar de 0x8E00 se le tuvo que pasar 0xEE00, con lo que las interrupciones 88 y 89 pasaron de ser interrupt gates con privilegio 0 a ser interrupt gates con privilegio 3. 

Luego se pedía cargar la Tarea 1 del archivo tareas.tsk y conmutarla.\\

En el archivo kernel.asm pusheamos en la pila (en la pila del kernel) los parámetros para llamar a cargar\_tarea, que son \code{indice}: 0x00000001 y \code{desde}: 0x00010000 (según se especifica en la sección 2.3 del enunciado del TP3)\\
Se hace el call a cargar\_tarea y luego con un jmp far saltamos al descriptor de la TSS de la tarea 1 en la GDT. El offset es irrelevante, porque el procesador determina que no lo necesita, al reconocerlo como un descriptor de tareas.\\ 
\subsection{Preguntas}
\begin{itemize}
\item Pregunta 7: 
\end{itemize}

Antes de realizar el salto, el CPU se encuentra ejecutando código que se encuentra en un segmento de privilegio 0. El campo DPL, del descriptor de TSS de la tarea 1, debe ser, entonces, de privilegio 0, para que no ocurra General Protection Fault. Si no ocurre, es correcto.
Además, el Busy flag debe ser 0, puesto que un salto a una tarea ocupada también generaría un GP Fault.
La TSS debe tener valores válidos, de lo contrario hubiese ocurrido una Invalid TSS Fault, al saltar a la tarea.
\\
Una vez que se haya conmutado a la tarea 1. Corroboramos los valores con los que fue cargada la TSS por medio del comando de Bochs, info tss
También la entrada en la GDT, con info gdt 7 (el índice de la primera tarea en la GDT). Debe ser de tipo TSS de 32 bits, y su estado debe ser Busy, en contraste con la tarea 0 (que es en realidad un “dummy TSS”, usada sólo para tener donde guardar el contexto al momento de realizar la conmutación.
\\
El correcto copiado del código puede hacerse con una inspección poco exhaustiva (con la consiguiente dependencia de Fe en Dios) usando xp /100b memoria o con una rutina que compare los 8Kb de código de la tarea 1 que comienza en la dirección física 0x00010000 (código original) con la que está en la primeras páginas libres de usuario.

\subsection{Preguntas}
\begin{itemize}
\item Pregunta 8: ¿Cómo se puede verificar si la conmutación de una tarea fue exitosa?
\end{itemize}

Para verificar si la tarea fue exitosamente conmutada, tenemos que ver en qué estado se encuentra el bit Busy en el descriptor de la TSS en la GDT. Esto lo hacemos con info GDT. Tambien tenemos que ver que el contexto de la tarea se haya cargado correctamente. Verificamos con info TSS el contexto que tenía y lo comparamos con info reg que nos dice el contexto actual.

\begin{itemize}
\item Pregunta 9: Se sabe que las tareas llaman a la interrupciones 88 y 89 y por eso debe 
realizarse el segundo inciso de este ejercicio antes de conmutar de tarea. ¿Qué ocurre si 
 no se hace? ¿Por qué? 
\end{itemize}

El segundo ejercicio dice “Modifique la IDT para que las interrupciones 88 y 89 puedan ser llamadas desde privilegio 3 ”.  Si no se hace, se genera una General Protection Exception.
Las tareas que utilizamos corren en modo usuario (nivel de privilegio 3) mientras que el kernel tiene nivel de privilegio 0. 
Si no se modificaran las interrupciones 88 y 89, se encontrarian en modo kernel y las tareas que tienen privilegios mas bajos, intentarian ejecutar código de privilegio mas alto, produciendo la excepción.
